package com.haixee.parkdemo.gateway.security;

import com.haixee.parkdemo.common.entity.AuthData;
import com.haixee.parkdemo.common.response.ResResult;
import com.haixee.parkdemo.gateway.client.AuthService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.security.web.server.context.ServerSecurityContextRepository;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.security.auth.login.AccountNotFoundException;
import java.util.List;

@Component
public class DefaultSecurityContextRepository implements ServerSecurityContextRepository {

    public final static String TOKEN_HEADER = "Authorization";

    public final static String BEARER = "Bearer ";

    @Autowired
    private AuthService authService;

    @Override
    public Mono<Void> save(ServerWebExchange exchange, SecurityContext context) {
        return Mono.empty();
    }

    @Override
    public Mono<SecurityContext> load(ServerWebExchange exchange) {
        ServerHttpRequest request = exchange.getRequest();
        List<String> headers = request.getHeaders().get(TOKEN_HEADER);

        String token = null;

        if (!CollectionUtils.isEmpty(headers)) {
            String authorization = headers.get(0);
            if (StringUtils.isNotEmpty(authorization)) {
                token = authorization.substring(BEARER.length());
            }
        }

        byte method;
        if (request.getMethod() == HttpMethod.GET) {
            method = 1;
        } else {
            method = 2;
        }

        if (request.getMethod() == HttpMethod.OPTIONS) {
            return Mono.just(
                    new UsernamePasswordAuthenticationToken(new AuthData().setAuth(true), null)
            ).map(SecurityContextImpl::new);
        }


        ResResult<AuthData> auth = authService.getAuth(token, method, request.getPath().toString());

        if (auth.getCode() != 0 || !auth.getData().getAuth()) {
//            return Mono.error(new AccountNotFoundException());
            return Mono.just(
                    new UsernamePasswordAuthenticationToken(null, null)
            ).map(SecurityContextImpl::new);
        }
        return Mono.just(
                new UsernamePasswordAuthenticationToken(auth.getData(), null)
        ).map(SecurityContextImpl::new);


//        return Mono.just(new SecurityContextImpl(new UsernamePasswordAuthenticationToken(null, null)));
    }

}
